import {
  Injectable,
  CanActivate,
  ExecutionContext,
  ForbiddenException,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';

import { REQUIRE_PERMISSION_KEY } from '@src/common/decorator/require-permission.decorator';
import { RedisService } from '@src/redis/redis.service';

import { JwtPayload } from '../type/jwt-payload.type';

@Injectable()
export class PermissionGuard implements CanActivate {
  constructor(
    private reflector: Reflector,
    private redisService: RedisService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const requiredCodes = this.reflector.getAllAndOverride<string[]>(
      REQUIRE_PERMISSION_KEY,
      [context.getHandler(), context.getClass()],
    );

    if (!requiredCodes?.length) return true;

    const request = context.switchToHttp().getRequest();
    const user = request.user as JwtPayload;
    if (!user) throw new ForbiddenException('请先登录');

    const cachedPerms = await this.redisService.get<string[]>(
      RedisService.key.userPerms(`${user.sub}`),
    );
    if (!cachedPerms) {
      throw new ForbiddenException('权限信息已过期，请重新登录');
    }

    const hasPermission = requiredCodes.some((code) =>
      cachedPerms.includes(code),
    );

    if (!hasPermission) {
      throw new ForbiddenException('权限不足');
    }

    return true;
  }
}
